
#include <pthread.h>

#include <map>
#include <string>


// A simple class to store individual messages.
struct BBMessage
{
public:
    BBMessage( int id, const std::string & user, const std::string & message );
    BBMessage();

    int id() const;
    std::string user() const;
    std::string text() const;

private:
    int m_id;
    std::string m_user;
    std::string m_text;
};


// A class to message/file handling. Does everything but networking.
class BulletinBoard
{
public:
    
    enum ErrorCode
    {
        NoError = 0,
        IdNotFound = -1,
        ErrorOpeningForReading = -2,
        ErrorWhileReading = -3,
        ErrorOpeningForWriting = -4,
        ErrorWhileWriting = -5,
        ErrorSendingToOtherServers = -6,
        ErrorParsingLine = -7
    };

    BulletinBoard();
    ~BulletinBoard();

    // Tells the BB which file to use as its "database".
    void setFileName( const std::string & file );

    // Takes a single command, parses it, performs the associated operation,
    // and returns the response message. user is an input-output parameter
    // which takes the current user name and changes it if needed. done is an
    // output variable that indicates that the current client has quit.
    std::string interpretCommand( const std::string & command, std::string & user, bool & done );

    // Removes the last written message from the file. Used to abort a
    // failed commit.
    int undoLastWrite();

    // Writes the given message to the bulletin board.
    int writeMessage( const std::string & message );

    // Returns the last known message id.
    int lastMessageId();

private:
    // Loads the database, if needed, and returns an error code.
    int load();

    // Retrieves the message with the given ID, copies it into message and
    // returns an error code.
    int read( int messageId, BBMessage & line );

    bool m_loaded;
    int m_lastUsedId;
    int m_undoFileSize;
    std::string m_fileName;
    std::map<int,BBMessage> m_messages;
    pthread_rwlock_t m_rwlock;
};